﻿
using GoodDotNet.Core.Data;
using GoodDotNet.Core.IRepository.BASE;
using GoodDotNet.Core.Model;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace GoodDotNet.Core.Repository.BASE
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
    {
        internal MyDbContext context;
        internal DbSet<TEntity> dbSet;


        public BaseRepository(MyDbContext context)
        {
            this.context = context;
            this.dbSet = context.Set<TEntity>();
        }

        public IQueryable<TEntity> query()
        {
            return dbSet;
        }
        public IQueryable<TEntity> query(Expression<Func<TEntity, bool>> condition)
        {
            return dbSet.Where(condition);
        }

        public List<TEntity> GetList()
        {
            return dbSet.ToList();
        }
        public List<TEntity> GetList(Expression<Func<TEntity, bool>> condition)
        {
            return dbSet.Where(condition).ToList();
        }

        public List<IResult> GetList<IResult>(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, IResult>> select)
        {
            return dbSet.AsNoTracking().Where(condition).Select(select).ToList();

        }
        public List<TEntity> GetListOrderBy(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, object>> order)
        {
            return dbSet.Where(condition).OrderBy(order).ToList();
        }
        public List<IResult> GetListOrderBy<IResult>(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, IResult>> select, Expression<Func<IResult, object>> order)
        {
            return dbSet.AsNoTracking().Where(condition).Select(select).OrderBy(order).ToList();
        }
        public List<TEntity> GetListOrderByDesc(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, object>> order)
        {
            return dbSet.Where(condition).OrderByDescending(order).ToList();
        }
        public List<IResult> GetListOrderByDesc<IResult>(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, IResult>> select, Expression<Func<IResult, object>> order)
        {
            return dbSet.AsNoTracking().Where(condition).Select(select).OrderByDescending(order).ToList();
        }
        public List<TEntity> PageListOrderBy<IResult>(
              PagingPar pagingPar,
              Expression<Func<TEntity, bool>>? condition,
              Expression<Func<TEntity, object>>? order
           )
        {
            var query = dbSet.AsNoTracking();
            if (condition != null)
            {
                query = query.Where(condition);
            }
            if (order != null)
            {
                query = query.OrderBy(order);
            }
            return query.Skip(((int)pagingPar.PageIndex - 1) * (int)pagingPar.PageSize)
                .Take((int)pagingPar.PageSize)
                .ToList();
        }

        /// <summary>
        /// 倒序查询
        /// </summary>
        /// <typeparam name="IResult"></typeparam>
        /// <param name="pagingPar">分页参数</param>
        /// <param name="condition">查询条件</param>
        /// <param name="order">排序条件</param>
        /// <returns></returns>
        public List<TEntity> PageListOrderByDesc<IResult>(
              PagingPar pagingPar,
              Expression<Func<TEntity, bool>>? condition,
              Expression<Func<TEntity, object>>? order
           )
        {
            var query = dbSet.AsNoTracking();
            if (condition != null)
            {
                query = query.Where(condition);
            }
            if (order != null)
            {
                query = query.OrderByDescending(order);
            }
            return query.Skip(((int)pagingPar.PageIndex - 1) * (int)pagingPar.PageSize)
                .Take((int)pagingPar.PageSize)
                .ToList();
        }


        public List<TEntity> PageList<IResult>(
           PagingPar pagingPar
          )
        {
            var query = dbSet.AsNoTracking();

            return query
              .Skip(((int)pagingPar.PageIndex - 1) * (int)pagingPar.PageSize)
              .Take((int)pagingPar.PageSize)
              .ToList();
        }
        public List<TEntity> PageList<IResult>(
          PagingPar pagingPar,
        Expression<Func<TEntity, bool>> condition
        )
        {
            var query = dbSet.AsNoTracking();

            query = query.Where(condition);

            return query
              .Skip(((int)pagingPar.PageIndex - 1) * (int)pagingPar.PageSize)
              .Take((int)pagingPar.PageSize)
              .ToList();
        }
        public List<IResult> PageList<IResult>(
           PagingPar pagingPar,
          Expression<Func<TEntity, bool>>? condition,
          Expression<Func<TEntity, IResult>> select

          )
        {
            var query = dbSet.AsNoTracking();
            if (condition != null)
            {
                query = query.Where(condition);
            }
            return query
              .Select(select)
              .Skip(((int)pagingPar.PageIndex - 1) * (int)pagingPar.PageSize)
              .Take((int)pagingPar.PageSize)
              .ToList();
        }
        public TEntity? Get(Expression<Func<TEntity, bool>> condition)
        {
            return dbSet.Where(condition).FirstOrDefault();
        }
        public IResult Get<IResult>(Expression<Func<TEntity, bool>> condition, Expression<Func<TEntity, IResult>> select)
        {
            return dbSet.AsNoTracking().Where(condition).Select(select).FirstOrDefault();
        }
        public int Count(Expression<Func<TEntity, bool>>? condition)
        {
            return dbSet.Where(condition).Count();
        }
        public int Count()
        {
            return dbSet.Count();
        }
        public TEntity? GetNoTrack(Expression<Func<TEntity, bool>> condition)
        {
            return dbSet.AsNoTracking().Where(condition).FirstOrDefault();
        }
        /// <summary>
        /// 写入实体数据
        /// </summary>
        /// <param name="entity">博文实体类</param>
        /// <returns></returns>
        public void Add(TEntity entity)
        {
            var property = typeof(TEntity).GetProperty("InsertTime");
            if (property != null)
            {
                if (property.GetValue(entity, null) == null)
                {
                    property.SetValue(entity, DateTime.Now);
                }
            }
            dbSet.Add(entity);

        }
        /// <summary>
        /// 更新实体数据
        /// </summary>
        /// <param name="entity"></param>
        public void Update(TEntity entity)
        {
            var property = typeof(TEntity).GetProperty("UpdateTime");
            if (property != null)
            {
                property.SetValue(entity, DateTime.Now);
            }
            dbSet.Update(entity);
        }
        /// <summary>
        /// 更新实体数据
        /// </summary>
        /// <param name="entity"></param>
        public void Update(List<TEntity> entitys)
        {
            foreach (var entity in entitys)
            {
                var property = typeof(TEntity).GetProperty("UpdateTime");
                if (property != null)
                {
                    property.SetValue(entity, DateTime.Now);
                }
            }
            dbSet.UpdateRange(entitys);
        }
        /// <summary>
        /// 条件删除
        /// </summary>
        /// <param name="conde"></param>
        public async void Remove(Expression<Func<TEntity, bool>> conde)
        {
            var entity = dbSet.Where(conde);
            var property = typeof(TEntity).GetProperty("Deleted");
            if (property != null)
            {
                await entity.ForEachAsync(e =>
                {
                    property.SetValue(e, 1);
                });
                dbSet.UpdateRange(entity);
            }
            else
            {
                dbSet.RemoveRange(entity);
            }
        }

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="entity"></param>
        public void Remove(TEntity entity)
        {
            var property = typeof(TEntity).GetProperty("Deleted");
            if (property != null)
            {
                property.SetValue(entity, 1);
                dbSet.Update(entity);
            }
            else
            {
                dbSet.Remove(entity);
            }
        }

        /// <summary>
        /// 通过sql查询
        /// </summary>
        /// <param name="sql"></param>
        /// <returns></returns>

        public IQueryable<TEntity> FromSql(FormattableString sql)
        {
            return dbSet.FromSql<TEntity>(sql);
        }
        /// <summary>
        /// 运行sql命令
        /// </summary>
        /// <param name="sql">sql语句</param>
        public int ExecuteSql(FormattableString sql)
        {
            return context.Database.ExecuteSql(sql);
        }

    }
}
